#include "stdafx.h"

#include <ctime>
#include <QSound>

#include "WinApiWarp.h"
#include "TSearcherWindow.h"
#include "Task.h"

#include "HelperFunctions.h"
#include "GuiTaskManager.h"
#include "Constants.h"




void mouseclick()
{
    mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}

void keydown(DWORD vk, unsigned int delay /*= 10*/)
{
    keybd_event(vk, 0, 0, 0);
    if (delay)
        Sleep(delay);
}

void keyup(DWORD vk, unsigned int delay /*= 10*/)
{
    keybd_event(vk, 0, KEYEVENTF_KEYUP, 0);
    if (delay)
        Sleep(delay);
}

void pressKey(DWORD vk, unsigned int downDelay /*= 5*/, unsigned int upDelay /*= 5*/)
{
    keydown(vk, downDelay);
    keyup(vk, upDelay);
}

void pressCombine2(DWORD vkcontrol, DWORD vk, unsigned int downDelay /*= 15*/, unsigned int upDelay /*= 25*/)
{
    keydown(vkcontrol, 100);
    keydown(vk, downDelay);
    keyup(vk, 100);
    keyup(vkcontrol, upDelay);
}

QPixmap captureFullScreen()
{
    pressKey(VK_SNAPSHOT, 0);
    Sleep(400);

    playSound(Constants::audioPath.capture);
    return QApplication::clipboard()->pixmap();
}

void captureActiveWindow()
{
    pressCombine2(VK_MENU, VK_SNAPSHOT);

    playSound(Constants::audioPath.capture);
}

void pressControlV()
{
    pressCombine2(VK_CONTROL, 'V');
}

void pressAltS()
{
    pressCombine2(VK_MENU, 'S');
}

void bringFirefoxWindowToTopGentlly(const QString &firefoxKeywrod)
{
    auto window = findFirefoxWindow(firefoxKeywrod);
    if (window)
    {
        bringWindowToTopGentlly(window);
    }
}

void bringWindowToTopGentlly(HWND window)
{
    bringWindowToTop(window);
    Sleep(800);
}

void captureActiveWindowGentlly()
{
    captureActiveWindow();
    Sleep(1000);
}

QPixmap captureWindow(HWND window)
{
    bringWindowToTopGentlly(window);

    captureActiveWindowGentlly();
    Sleep(1000);

    return QApplication::clipboard()->pixmap();
}

void pressControlVGentlly()
{
    pressControlV();
    Sleep(1000);
}

DWORD point2lparam(short x, short y)
{
    return x | y << 16;
}

void makeQQPasteAndSend(HWND qqWindow)
{
    bringWindowToTopGentlly(qqWindow);

    auto finit = qqFeature(qqWindow);
    QImage((uchar *)finit.data.data(), 150, 62, QImage::Format_RGB32).save("D:\\finit.png");
    for (int i = 0; i < 5; i++)
    {
        bringWindowToTopGentlly(qqWindow);

        // ctrl + v
        pressControlV();
        Sleep(1000);

        // check if image(or, word) is pasted
        auto f1 = qqFeature(qqWindow);
        QImage((uchar *)f1.data.data(), 150, 62, QImage::Format_RGB32).save("D:\\f1.png");
        auto diffCount = f1.diffCount(finit);
        if (diffCount > 100)
            break;
    }
    pressAltS();
}

bool shotFirefoxAndSendToQQ(const QString& firefoxKeyword, const QString &QQKeyword, const QString &description, Task *task)
{
    if (QQKeyword.length() == 0)
        return false;

    // wait one second for every thing should change changed.
    Sleep(1000);
    auto ffWindow = findFirefoxWindow(firefoxKeyword);
    auto qqWindow = getSupportQQWindow(QQKeyword);

    if (!ffWindow)
        return false;

    TSearcherWindow::instance()->taskHelper()->guiTaskWait<void>([]()
    {
        TSearcherWindow::instance()->hide();
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    });
    auto pixmap = captureFullScreen();
    TSearcherWindow::instance()->taskHelper()->guiTaskWait<void>([]()
    {
        TSearcherWindow::instance()->show();
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    });
    task->saveImage(description, pixmap);

    if(qqWindow)
    {
        makeQQPasteAndSend(qqWindow);

        bringWindowToTopGentlly(ffWindow);
        return true;
    }
    return false;
}

HWND findWindow(const QString windowClass, const QString &name)
{
    wchar_t *wcsClass = windowClass.count() == 0 ? nullptr : (wchar_t*)windowClass.utf16();
    clock_t start = clock();
    wchar_t title[1024];
    wchar_t *res;
    HWND window = nullptr;
    do
    {
        QCoreApplication::processEvents();
        window = FindWindowEx(nullptr, window, wcsClass, nullptr);
        GetWindowText(window, title, sizeof(title)/sizeof(wchar_t) - 1);
        res = wcsstr(title, (wchar_t *)name.utf16());
        if (clock() - start > CLOCKS_PER_SEC * 0.5)
            return nullptr;
    } while (res == nullptr);
    return window;
}

HWND findQQWindow(const QString &name)
{
    return findWindow("TXGuiFoundation", name);
}

HWND findFirefoxWindow(const QString &name)
{
    return findWindow("MozillaWindowClass", name);
}

void bringWindowToTop(HWND window)
{
    //QCoreApplication::processEvents();
    if (window)
    {
        wchar_t title[1024];
        GetWindowText(window, title, sizeof(title) / sizeof(wchar_t) - 2);

        //AttachThreadInput(
        //    GetWindowThreadProcessId(
        //    ::GetForegroundWindow(), NULL),
        //    GetCurrentThreadId(), TRUE);

        //SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREPOSITION | SWP_SHOWWINDOW);
        if (IsIconic(window))
            ShowWindow(window, SW_RESTORE);
        //ShowWindow(window, SW_SHOW);

        SetWindowPos(window, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREPOSITION | SWP_SHOWWINDOW);

        SetForegroundWindow(window);
    }
}

HWND getSupportQQWindow(const QString &keyword)
{
    return findQQWindow(keyword);
}

void sendChar(HWND window, int charactor)
{
    SendMessage(window, WM_CHAR, charactor, 0);
}

void sendString(HWND window, const QString &str)
{
    wchar_t *wcs = (wchar_t *)str.utf16();
    while (*wcs)
    {
        sendChar(window, *wcs++);
        Sleep(400);
    }
}

Feature qqFeature(HWND qqWindow)
{
    RECT qqRect = windowRect(qqWindow);
    auto height = qqRect.bottom - qqRect.top;
    auto width = qqRect.right - qqRect.left;
    auto x = qqRect.left;
    auto y = qqRect.top;

    auto getFeatureRect = [](int qqX, int qqY, int qqWidth, int qqHeight)
    {
        auto width = 150;
        auto height = 62;
        return RECT{ qqX + 13, qqY + qqHeight - 110, qqX + 13 + 150, qqY + qqHeight - 48 };
    };
    RECT featureRect = getFeatureRect(x, y, width, height);
    LONG featureX = featureRect.left;
    LONG featureY = featureRect.top;
    LONG featureWidth = featureRect.right - featureRect.left;
    LONG featureHeight = featureRect.bottom - featureRect.top;

    HWND desktop = ::GetDesktopWindow();
    WindowDC desktopDC(desktop);
    RECT desktopRect = windowRect(desktop);
    auto deskHeight = desktopRect.bottom - desktopRect.top;
    auto deskWidth = desktopRect.right - desktopRect.left;

    CompatibleDC memDC(desktopDC);
    CompatibleBitmap bitmap(desktopDC, featureWidth, featureHeight);
    bitmap.use(memDC);

    BitBlt(memDC, 0, 0, featureWidth, featureHeight, desktopDC, featureX, featureY, SRCCOPY);

    BITMAPINFO bi = { 0 };
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
    bi.bmiHeader.biWidth = featureWidth;
    bi.bmiHeader.biHeight = -featureHeight;
    bi.bmiHeader.biPlanes = 1;
    bi.bmiHeader.biBitCount = 32;
    bi.bmiHeader.biCompression = BI_RGB;
    auto sizePerLine = (bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount / 8 + 31) / 32 * 32;
    bi.bmiHeader.biSizeImage = sizePerLine * std::abs(bi.bmiHeader.biHeight);
    Feature f;
    f.data.resize(bi.bmiHeader.biSizeImage);
    //unsigned char *data = new unsigned char[bi.bmiHeader.biSizeImage];
    auto data = f.data.data();
    auto read = ::GetDIBits(memDC, bitmap, 0, std::abs(bi.bmiHeader.biHeight), data, &bi, DIB_RGB_COLORS);

    return f;
}

void playSound(const QString &path)
{
#pragma comment(lib, "Winmm.lib")
    ::PlaySoundW((wchar_t *)path.utf16(), NULL, SND_FILENAME | SND_NODEFAULT);
}
